/*
 * Copyright (c) 2001 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.p4eclipse.ui.action;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sourceforge.p4eclipse.core.PerforceException;
import net.sourceforge.p4eclipse.core.PerforceRepositoryProvider;
import net.sourceforge.p4eclipse.core.Policy;
import net.sourceforge.p4eclipse.core.api.IChangeResult;
import net.sourceforge.p4eclipse.core.api.IChangesResult;
import net.sourceforge.p4eclipse.core.api.IInfoResult;
import net.sourceforge.p4eclipse.ui.PerforceUIPlugin;
import net.sourceforge.p4eclipse.ui.dialogs.ConfirmationDialog;
import net.sourceforge.p4eclipse.ui.views.PendingChangelistView;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.internal.ui.actions.TeamAction;
import org.eclipse.ui.actions.WorkspaceModifyOperation;

/**
  * @version 	$Revision: 23 $
  * @author		<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class RevertUnchangedFilesAction extends TeamAction
{
	/** @see TeamAction#isEnabled() */
	protected boolean isEnabled() 
		throws TeamException
	{
		IChangesResult[] changesResults = getSelectedChangesResult();
		if (changesResults.length != 1)
			return false;
			
		IInfoResult infoResult = PerforceUIPlugin.getClient().info();
		if (!(infoResult.getClientName().equals(changesResults[0].getClientName())))
			return false;
			
		return true;
	}

	/** @see IActionDelegate#run(IAction) */
	public void run(IAction action)
	{
		run(
			new WorkspaceModifyOperation()
			{
				public void execute(IProgressMonitor monitor)
					throws InvocationTargetException, InterruptedException
				{
					IChangesResult[] changesResults = getSelectedChangesResult();
					Policy.assertTrue(changesResults.length == 1);
					
					Integer changelist = changesResults[0].getChangelist();
					try
					{
						final String[] files = 
							PerforceUIPlugin.getClient().diff(
								getFilesOfChangelist(changelist));
						if (files.length == 0)
						{
							return;
						}
						
						Display display = Display.getCurrent();
						if (display == null)
						{
							display = Display.getDefault();
						}
						
						final boolean[] doRevert = { false };
						display.syncExec(new Runnable() 
						{
							public void run() 
							{
								String message =
									"The following opened files do not differ " +
									"from the versions in the depot. Do you " +
									"want to revert them?";
									
								doRevert[0] = 
									ConfirmationDialog.openConfirmation(null, "Revert Unchanged Files", message, files);
							}
						});	
						
						if (doRevert[0])
						{
							PerforceUIPlugin.getClient().revert(files);
							
							IWorkspaceRoot root = 
								ResourcesPlugin.getWorkspace().getRoot();
								
							IFile[] fileResources = new IFile[files.length];
							for (int i = 0, length = files.length; i < length; i++)
							{
								fileResources[i] = root.getFileForLocation(
									new Path(files[i]));
							}
							refreshState(fileResources);
							
							display.asyncExec(new Runnable() 
							{
								public void run() 
								{
									PendingChangelistView.getInstance().refreshClientChangelists();
								}
							});						
						}					
					}
					catch (PerforceException e)
					{
						throw new InvocationTargetException(e);
					}
				}
			}, "RevertUnchangedFilesAction failed.", PROGRESS_DIALOG);
	}

	private String[] getFilesOfChangelist(Integer changelist) 
		throws PerforceException 
	{
		IChangeResult changeResult =
			PerforceUIPlugin.getClient().change(changelist);
			
		Map specDataMap =
			changeResult.getChangeSpecData().getSpecDataMap();
		List files = new ArrayList();
		for (Iterator it = specDataMap.entrySet().iterator();
		     it.hasNext(); )
		{
			Map.Entry entry = (Map.Entry)it.next();
			
			if (((String)entry.getKey()).startsWith("Files"))
			{
				files.add(entry.getValue());
			}
		}
		
		return (String[])files.toArray(new String[files.size()]);
	}

	/**
	  * Returns an array of all selected IChangesResult objects.
	  */
	private IChangesResult[] getSelectedChangesResult()
	{
		ArrayList resources = null;
		if (!selection.isEmpty())
		{
			resources = new ArrayList();
			for (Iterator elements = ((IStructuredSelection)selection).iterator(); elements.hasNext(); )
			{
				Object next = elements.next();
				
				if (next instanceof IChangesResult)
				{
					resources.add(next);
					continue;
				}
				else
				if (next instanceof IAdaptable)
				{
					IAdaptable a = (IAdaptable) next;
					Object adapter = a.getAdapter(IChangesResult.class);
					if (adapter instanceof IChangesResult)
					{
						resources.add(adapter);
						continue;
					}
				}
			}
		}
		
		if (resources != null && !resources.isEmpty())
		{
			IChangesResult[] result = new IChangesResult[resources.size()];
			resources.toArray(result);
			return result;
		}
		
		return new IChangesResult[0];
	}

	private void refreshState(IFile[] files)
	{
		PerforceRepositoryProvider provider =
			(PerforceRepositoryProvider) RepositoryProvider.getProvider(
				files[0].getProject());
	
		try
		{		
			provider.refreshState(files, IResource.DEPTH_ZERO, new NullProgressMonitor());
		}
		catch (TeamException e)
		{
			PerforceUIPlugin.log(e.getStatus());
		}
	}	
}
